package com.transaction.stockseata.utils;

import org.springframework.http.MediaType;
import org.springframework.security.crypto.codec.Utf8;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

/**
 * @author ausu
 * @version 1.0
 * @description: TODO
 *               1。通过IO流将数据读取出来并存入到一个byte数组中，
 *               2. 然后重新getReader和getInputStream方法，在这两个读取流的方法中，
 *               都从byte数组中返回IO流数据出来，这样就实现了反复读取了。
 * @date 2023/1/30 14:33
 */
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
    // 读取一行数据
    private final byte[] body;

    /**
     * Constructs a request object wrapping the given request.
     *
     * @param request The request to wrap

     * @throws IllegalArgumentException if the request is null
     */
    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {
        super(request);
        request.setCharacterEncoding(String.valueOf(StandardCharsets.UTF_8));
        response.setCharacterEncoding(String.valueOf(StandardCharsets.UTF_8));
        body = request.getReader().readLine().getBytes(String.valueOf(StandardCharsets.UTF_8));
    }

    /**
     * The default behavior of this method is to return getReader() on the
     * wrapped request object.
     */
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    /**
     * The default behavior of this method is to return getInputStream() on the
     * wrapped request object.
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {

            }

            @Override
            public int available() throws IOException {
                return body.length;
            }

            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
    }
}
